home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Original Shareware 1.1
/
The Original Shareware (WeMake CDs)(Volume 1.1)(CDs, Inc)(1993).iso
/
19
/
madtrb14.zip
/
TURBUTIL.PAS
< prev
next >
Wrap
Pascal/Delphi Source File
|
1985-06-22
|
54KB
|
1,664 lines
{***************************************************************************
* *
* Util.Pas *
* This source file by Jim Nutt *
* CIS 76044,1155 *
* CIS 71076,1434 *
* FIDO Jim Nutt @ #452 *
* *
* First Uploaded to DL1 of the Borland SIG on CIS November 30, 1984 *
* This revision 05/24/85 *
* When you get this file please notify me at FIDO #452, I am going to *
* attempt to track its distribution. Thank you, Jim Nutt *
* *
* This Module Comprises the various utility routines used by the other *
* modules in the program. Routines included in this module are: *
* *
* Routine Use *
* * 1 Upper_Left_X Returns the left x coordinate of active window *
* * 2 Upper_Left_Y Returns the upper y coord of active window *
* * 3 Lower_Right_X Returns the right x coord of active window *
* * 4 Lower_Right_Y Returns the lower y coord of active window *
* * 5 RvsOn Turns on Reverse Video *
* * 6 RvsOff Turns off Reverse Video *
* 7 Yes Prints a prompt, if user inputs 'Y' returns *
* Trues, otherwise returns False *
* * 8 Click Produces a single click from the PC speaker *
* * 9 Alert Prints a message to the screen and makes noise *
* * 10 Beep Makes noise for a specified period of time *
* 11 Replicate Duplicates a character a specified no. of times*
* 12 Left Left justifys a string in a field of spaces *
* 13 Center Centers a string in a field of specified width *
* 14 Get_Payment_Amount Calculates a loan payment amount *
* 15 Write_Neatly Outputs numbers with commas *
* 16 Get_Str Writes a string to the screen, allows it to be *
* edited and returns the terminating character *
* 17 Get_Num Does for numbers what Get_Str does for strings *
* * 18 Frame Frames a specified portion of the screen *
* * 19 UnFrame Removes the frame from the screen *
* * 20 Menu Displays a menu and gets a user input *
* * 21 Clear_Window Clears the screen within a window *
* * 22 Window_Frame Sets up, frames and titles a screen window *
* * 28 Push_Screen Saves the current screen *
* * 29 Pop_Screen Restores a saved screen *
* 30 Inc Increments an integer by 1 *
* 31 Dec Decrements an integer by 1 *
* 34 Upper Convert String to Upper Case *
* 35 Lower Convert String to Lower Case *
* 39 Power Raises a number to a power *
* * 43 Marquee Display Marquee and put message in it *
* * 44 Help Displays an appropriate help screen *
* * 48 GetForm generalized input routine *
* * 49 Date gets the date from the system *
* * 50 Time gets time from system *
* * 51 Push_Window pushes a small section of the screen *
* *
* * Indicates that the routine has IBM PC specific sections and would need*
* to be modified for other computers *
****************************************************************************}
procedure color(fc,bc : byte);
begin
textcolor(fc);
textbackground(bc);
end;
procedure highvideo;
begin
textcolor(white);
textbackground(back_ground_color);
end;
procedure normvideo;
begin
textcolor(white);
textbackground(back_ground_color);
end;
procedure lowvideo;
begin
textcolor(lightgray);
textbackground(back_ground_color);
end;
{****************************************************************************}
function upper_left_x : integer; {* These four routines allow a *}
{1*} {* routine to adjust its output *}
begin {* according to what size window it *}
upper_left_x := mem[dseg:$4] + 1; {* is operating in. They are *}
end; {* compatible only with Turbo Pascal *}
{* version 3 on an IBM PC or *}
function upper_left_y : integer; {* compatible *}
{2*}
begin
upper_left_y := mem[dseg:$5] + 1;
end;
var
{3*}
lower_right_x : byte absolute cseg: $16a;
{4*}
lower_right_y : byte absolute cseg: $16b;
{****************************************************************************}
procedure rvson; {* These two routines turn on and *}
{5*} {* off Reverse video on the IBM PC *}
begin {*************************************}
textcolor(0);
textbackground(7);
end;
procedure rvsoff;
{6*}
begin
normvideo;
end;
{30**************************************************************************}
procedure inc( {* Increment argument by One *}
var i : integer); {*****************************************}
begin
i := i + 1;
end;
{31**************************************************************************}
procedure dec( {* Decrement argument by One *}
var i : integer); {*****************************************}
begin
i := i - 1;
end;
{26**************************************************************************}
procedure wait; {* Wait for a keypress from the KBD *}
{**************************************}
var
anykey : char;
begin
read(kbd,anykey);
end;
{****************************************************************************}
type {* Just a couple(?) of type declarations*}
menu_item = string[40]; {* needed for a number of routines *}
{*************************************}
menu_selections = array[1..30] of menu_item;
long_string = string[255];
register = record
ax,bx,cx,dx,bp,si,di,ds,es,flags : integer;
end;
screenloc = record
ch : char;
attrib : byte;
end;
video = array[1..25] of array[1..80] of screenloc;
video_ptr = ^video_stack;
vidscr = array[1..1] of screenloc;
charset = set of char;
video_stack = record
next_screen : video_ptr;
x1,y1,
x2,y2 : byte;
screen_store : ^vidscr;
end;
var
screenbuffer : video;
screen_stack : video_ptr;
screen : ^video;
com : integer;
helpcontext : integer;
screenfile : file of video;
const
valid_set : charset = [' '..'~'];
digits : charset = ['0'..'9'];
letters : charset = ['A'..'Z','a'..'z'];
uppercase : charset = [' '..'`','{'..'~'];
lowercase : charset = [' '..'@','['..'~'];
numbers : charset = ['0'..'9','e','E','+','-','.',','];
allchars : charset = [' '..'~'];
{7***************************************************************************}
function yes(prompt : long_string) : boolean;{* This routine prints PROMPT *}
{* to the screen and waits for *}
var {* the user to type either a *}
inchar : char; {* 'y' or 'n'. It is case *}
{* insensitive. If a 'y' is *}
begin {* entered, the function *}
write(prompt); {* returns TRUE. *}
repeat {*******************************}
read(kbd,inchar);
until inchar in ['Y','y','N','n'];
write(inchar);
yes := inchar in ['Y','y'];
end;
{34**************************************************************************}
function upper (s : long_string) {* Convert Strng S to Upper case *}
: long_string; {* Return uppercase string *}
{*************************************}
var
i : integer;
lcase : set of char;
begin
lcase := ['a'..'z'];
for i := 1 to length(s) do
if s[i] in lcase
then
s[i] := char(ord(s[i]) - 32);
upper := s;
end;
{35**************************************************************************}
function lower (s : long_string) {* Convert string S to lowercase *}
: long_string; {* Return lowercase string *}
{****************************************}
var
i : integer;
ucase : set of char;
begin
ucase := ['A'..'Z'];
for i := 1 to length(s) do
if s[i] in ucase
then
s[i] := char(ord(s[i]) + 32);
lower := s;
end;
{8***************************************************************************}
procedure click; {* Makes a clicking noise *
*************************************}
var f,n : integer;
begin
sound(2000);
delay(5);
nosound;
end;
{9***************************************************************************}
procedure alert(message : long_string);{* This routine prints MESSAGE to the*}
{* screen and makes an obnoxious *}
var {* noise for about 1 second *}
i : integer; {*************************************}
i1,i2,i3,i4 : integer;
begin
write(message);
for i4 := 1 to 10 do
begin
i2 := 250 + i4 * 25;
for i3 := 1 to 2 do
begin
for i1 := 1 to 30 - i3 * 2 do
begin
sound(i1 + i2 + i3 * 2);
delay(2);
end;
delay(5);
i2 := i2 + 30;
end;
nosound;
end;
end;
{21**************************************************************************}
procedure clear_window; {* Clear the Active window *}
{*******************************************}
var
i : integer;
begin
for i := 1 to lower_right_y - upper_left_y + 1 do
begin
gotoxy(1,i);
clreol;
end;
end;
{10**************************************************************************}
procedure beep(n : integer); {* This routine sounds a tone of frequency *}
{* N for approximately 100 ms *}
begin {********************************************}
sound(n);
delay(100);
nosound;
end;
{28**************************************************************************}
procedure push_screen; {* This routine stores the current *}
{* screen into a temporary storage *}
{* area *}
{**************************************}
var
temp : video_ptr;
i,j,k : integer;
begin
if (maxavail < 0) or (maxavail > 4096)
then
begin
if screen = nil
then
screen := ptr($b000,0);
new(temp);
temp^.x1 := 1;
temp^.y1 := 1;
temp^.x2 := 80;
temp^.y2 := 25;
getmem(temp^.screen_store,4000);
temp^.next_screen := screen_stack;
k := 1;
for i := 1 to 25 do
for j := 1 to 80 do
begin
temp^.screen_store^[k] := screen^[i][j];
inc(k);
end;
screen_stack := temp;
end
else
begin
alert('Insufficient Memory - You are being dumped');
halt;
end;
end;
{29**************************************************************************}
procedure pop_screen; {* This routine Pops a screen from the*}
{* Screen Stack *}
{**************************************}
var
temp : video_ptr;
i,j,k : integer;
begin
if screen = nil
then
screen := ptr($b000,0);
k := 1;
for i := screen_stack^.y1 to screen_stack^.y2 do
for j := screen_stack^.x1 to screen_stack^.x2 do
begin
screen^[i][j] := screen_stack^.screen_store^[k];
inc(k);
end;
temp := screen_stack;
screen_stack := screen_stack^.next_screen;
freemem(temp^.screen_store,
((temp^.x2 - temp^.x1 + 1) * (temp^.y2 - temp^.y1 + 1)) * 2);
dispose(temp);
end;
{43**************************************************************************}
procedure marquee {* Draws a marquee in center screen *}
(str : long_string);{* Around the input parameter *}
{***************************************}
const
onchr = #1;
offchr = #2;
var
i,j,k : integer;
x,y : integer;
astrsk : array[1..4] of record
x,y : integer;
oldx,oldy : integer;
xi,yi : integer;
end;
begin
window(1,1,80,25);
push_screen;
clrscr;
x := 40 - length(str) div 2 - 2;
for i := 10 to 14 do
begin
screen^[i][x].ch := onchr;
screen^[i][x].attrib := 7;
screen^[i][x + length(str) + 3].ch := onchr;
screen^[i][x + length(str) + 3].attrib := 7;
end;
for i := x to x + length(str) + 3 do
begin
screen^[10][i].ch := onchr;
screen^[14][i].ch := onchr;
screen^[10][i].attrib := 7;
screen^[14][i].attrib := 7;
end;
gotoxy(x+2,12);
highvideo;
write(str);
lowvideo;
astrsk[1].x := 40;
astrsk[1].y := 10;
astrsk[1].xi := 1;
astrsk[1].yi := 0;
astrsk[2].x := x;
astrsk[2].y := 12;
astrsk[2].xi := 0;
astrsk[2].yi := -1;
astrsk[3].x := x + length(str) + 3;
astrsk[3].y := 12;
astrsk[3].xi := 0;
astrsk[3].yi := 1;
astrsk[4].x := 40;
astrsk[4].y := 14;
astrsk[4].xi := -1;
astrsk[4].yi := 0;
astrsk[4].oldx := astrsk[1].x;
astrsk[4].oldy := astrsk[1].y;
astrsk[3].oldx := astrsk[2].x;
astrsk[3].oldy := astrsk[2].y;
astrsk[2].oldx := astrsk[3].x;
astrsk[2].oldy := astrsk[3].y;
astrsk[1].oldx := astrsk[4].x;
astrsk[1].oldy := astrsk[4].y;
k := 1;
repeat
if k > 4
then
k := 1;
j := astrsk[k].y;
i := astrsk[k].x;
if screen = ptr($b800,0)
then
repeat
until (port[$3da] and 1) = 1
else
repeat
until (port[$3ba] and 1) = 1;
screen^[j][i].ch := offchr;
screen^[astrsk[k].oldy][astrsk[k].oldx].ch := onchr;
screen^[j][i].attrib := 15;
screen^[astrsk[k].oldy][astrsk[k].oldx].attrib := 7;
astrsk[k].oldx := astrsk[k].x;
astrsk[k].oldy := astrsk[k].y;
i := i + astrsk[k].xi;
j := j + astrsk[k].yi;
if i > (x + length(str) + 3)
then
begin
i := i - astrsk[k].xi;
astrsk[k].xi := 0;
astrsk[k].yi := 1;
end;
if j > 14
then
begin
j := j - astrsk[k].yi;
astrsk[k].yi := 0;
astrsk[k].xi := -1;
end;
if i < x
then
begin
i := i - astrsk[k].xi;
astrsk[k].xi := 0;
astrsk[k].yi := -1;
end;
if j < 10
then
begin
j := j - astrsk[k].yi;
astrsk[k].yi := 0;
astrsk[k].xi := 1;
end;
astrsk[k].y := j;
astrsk[k].x := i;
inc(k);
until keypressed;
wait;
pop_screen;
end;
{44**************************************************************************}
procedure help; {* This routine reads a screen from the*}
{* Screen file and displays it *}
begin {***************************************}
push_screen;
{$I-}
seek(screenfile,helpcontext);
{$I+}
if ioresult = 0
then
begin
{$I-}
read(screenfile,screenbuffer);
{$I+}
screen^ := screenbuffer;
if ioresult <> 0
then
marquee('Sorry, I''m helpless in this situation')
else
wait;
end
else
marquee('Sorry, wish I could help you.');
pop_screen;
end;
{11**************************************************************************}
function replicate ( {* Repeat a character *}
count : integer; {* Number of Repititions *}
ascii : char {* Character to be repeated *}
) : long_string; {* String containing repeated *}
{* character *
* This function takes the character in 'Ascii', repeats it 'Count' times *
* and returns the resulting string as a 'Long_String' *
****************************************************************************}
var
temp : long_string; {Used to hold the incomplete result}
i : byte; {For Counter}
begin
temp := '';
for i := 1 to count do
temp := temp + ascii;
replicate := temp;
end; {Replicate}
{12*************************************************************************}
function left ( {* Left Justifies a string in a *}
str : long_string; {* field of spaces *}
width : integer {*************************************}
) : long_string;
begin
if length(str) > width
then
left := copy(str,1,width)
else
left := str + replicate(width - length(str),' ');
end;
{13**************************************************************************}
function center ( {* Centers a string in field *}
field_width : byte; {* Width of field for center *}
center_string : long_string {* String to Center *}
) : long_string; {* Return the string *}
{************************************************ *
* This functions takes the string 'Center_String' and centers it in a *
* field 'Field_Width' Spaces long. It returns a 'Long_String' with a *
* length equal to 'Field_Width'. If the 'Center_String' is longer than *
* field width, it is truncated on the right end and is not centered. *
****************************************************************************}
var
temp : long_string;
middle : byte;
num_ldg_blanks : byte;
begin
middle := field_width div 2;
num_ldg_blanks := middle - (length(center_string) div 2) - 1;
if length(center_string) > field_width
then
center := copy(center_string,1,field_width) {Truncate and return}
else
begin
temp := replicate(num_ldg_blanks,' ') +
center_string +
replicate(field_width - (num_ldg_blanks+length(center_string)),' ');
center := copy(temp, 1, field_width) {Truncate to Field_Width Characters}
end {Else}
end; {Center}
{39*************************************************************************}
function power(x : real; y : integer): {* This function raises X to the *}
real;
{* Yth power *}
{**********************************}
var
i : integer;
n : real;
begin
n := 1.0;
for i := 1 to y do
n := n * x;
power := n;
end; {Power}
{14*************************************************************************}
function get_payment_amount (loan_amount : real;
interest_rate : real;
amort_over : real
) : real;
var
monthly_interest_rate : real;
number_of_payments : integer;
begin
monthly_interest_rate := (interest_rate / 100.0) / 12.0;
number_of_payments := trunc (amort_over * 12);
get_payment_amount := loan_amount *
(1 / ((1 - 1 / power((1 + monthly_interest_rate),
number_of_payments))/
monthly_interest_rate));
end;
{15**************************************************************************}
procedure write_neatly ( {* Routine to write numbers *}
var outfile : text; {* output file *}
number : real; {* Number to be written *}
width : byte; {* Width of write area *}
max_dec : byte {* Number of decimal places *}
); {* This routine takes NUMBER, and *}
{* formats it with commas and *}
{* truncates to MAX_DEC decimal *}
{* places. If NUMBER is to big to *}
{* fit in WIDTH, then a row of *}
{* asterisks WIDTH long is output *}
{***********************************}
const
valid_digits : set of char = ['0'..'9','.','-','+','e'];
var
field : long_string;
point : integer;
i,j : integer; {Spares for counters}
begin
for i := 1 to max_dec do
number := number * 10;
number := number + 0.6;
for i := 1 to max_dec do
number := number / 10;
str(number:0:20,field); {Convert the input to a string}
i := 1;
i := pos('.',field); {Where's the Decimal!}
if i = 0
then
begin
field := field + '.'; {If no decimal, then add one}
point := length(field);
end
else
point := i;
i := point - 3; {Get the Point?}
while i > 1 do {put in commas, start at the back and work }
begin {to the front}
insert(',',field,i);
i := i - 3
end;
i := pos('.',field) - 1; {Find that pesky decimal}
j := 0;
while j <= max_dec do
begin
i := i + 1; {Pad to Max_Dec with zeros}
if i >= length(field)
then
field := field + '0';
j := j + 1;
end;
field := copy(field,1,i); {Clean it up a little and elimate trailers}
if max_dec = 0
then
field := copy(field,1,i - 1); {Truncate to integer if necessary}
if (length(field) > width) and (width > 0)
then
write(replicate(width,'*')) {Too Big! tell with asterisks}
else
write(outfile,field:width); {all that for this}
end;
{16**************************************************************************}
function get_str ( {* Get a string with editing *}
var in_str : long_string; {* String to be edited *}
buffer_len : integer; {* Its length *}
start_x : integer; {* Column to start in *}
y : integer; {* Row for input *}
force_case : boolean {* Force Input to Upper case *}
) : char; {* Return terminating Character *}
{* *}
{* This is a fairly versatile *}
{* string input and editing *}
{* routine. It takes IN_STRING *}
{* displays it at START_X,ROW *}
{* allows the user to edit the *}
{* string using WordStar(tm) *}
{* commands. It returns the *}
{* character used to terminate *}
{* input. By setting FORCE_CASE*}
{* true, all input is forced to *}
{* upper case *}
{********************************}
const
keyclick = true;
var
insert_mode : boolean;
done : boolean;
current_char : char;
x : byte;
escape : boolean;
current : char;
in_string : long_string;
begin
done := false; { ** }
insert_mode := false; { * Initialize starting variables}
gotoxy(start_x,y); { * }
x := start_x; { ** }
write(replicate(buffer_len,'_'));
in_string := in_str;
gotoxy(x,y);
write (in_string); {Write the initial value of the string}
gotoxy(x,y);
repeat {Start main edit/input loop}
if (x - start_x) = buffer_len
then
current_char := ^m {Terminate input if buffer is full}
else
read(kbd,current_char); {Get a character}
if (current_char = ^[) and not keypressed
then
begin
in_str := in_string;
get_str := ^[;
exit;
end;
if force_case
then
current_char := upcase(current_char); {force case if necessary}
repeat
escape := false;
case current_char of {Act on the current input}
^[ : if keypressed
then
begin
read(kbd,current_char);
escape := true;
case current_char of {Translate escape codes to}
'H' : current_char := ^e; {WordStar command codes }
'P' : current_char := ^x;
'K' : current_char := ^s;
'M' : current_char := ^d;
'S' : current_char := ^g;
'R' : current_char := ^v;
'<' : current_char := ^r;
's' : current_char := ^a;
't' : current_char := ^f;
';' : begin
help;
current_char := ^@;
end;
'D' : begin {Special Terminator}
done := true;
escape := false;
end;
'I' : begin
done := true;
escape := false;
end;
'Q' : begin
done := true;
escape := false;
end;
'O' : begin
done := true;
escape := false;
end;
'G' : begin
done := true;
escape := false;
end;
end; {Case}
end; {^[}
^e : done := true; {** }
{ ** All finished }
^x : done := true; {** }
^f : x := start_x + length(in_string);
^a : x := start_x;
^r : begin
in_string := in_str;
gotoxy(start_x,y);
write(replicate(buffer_len,'_'));
gotoxy(start_x,y);
write(in_string);
end;
^v : insert_mode := insert_mode xor true; {toggle insert}
^s : if x > start_x
then {non destructive backspace}
x := x - 1;
^h,#127 : if x > start_x
then {destructive backspace}
begin
delete(in_string, x - start_x, 1);
gotoxy(start_x,y);
write(in_string + '_');
x := x - 1;
end;
^d : if (x - start_x) < buffer_len
then {forward 1 character}
if (x - start_x) < length(in_string)
then
x := x + 1;
^g : begin
delete(in_string, x - start_x + 1,1); {delete character}
gotoxy(start_x,y); {under the cursor}
write(in_string + '_');
end;
^m : done := true; {**}
{ *** All Done}
^j : done := true; {**}
' '..'~' : if current_char in valid_set
then
if (x - start_x) >= length(in_string)
then
begin
in_string := in_string + current_char;
gotoxy(x,y);
write(current_char);
if (x - start_x) < buffer_len
then
x := x + 1;
end
else
if insert_mode
then {Just a run of the mill character}
begin {Insert Mode}
insert(current_char,in_string, x - start_x + 1);
in_string := copy(in_string,1,buffer_len);
gotoxy(start_x,y);
write(in_string);
if (x - start_x) < buffer_len
then
x := x + 1;
gotoxy(x,y);
end
else
begin {OverWrite Mode}
in_string[x - start_x + 1] := current_char;
gotoxy(x,y);
write(current_char);
if (x - start_x) < buffer_len
then
x := x + 1;
end
else
beep(1720)
end; {Case}
until not escape;
gotoxy(x,y);
if keyclick
then
click;
until done;
get_str := current_char; {Return the terminator}
in_str := in_string;
end;
{17**************************************************************************}
function get_num ( {* This routine gets number from user *}
var value : real; {* Current Value and Returned Value *}
decimals : integer;{* Number of Decimal Places *}
min_value : real; {* Minimum Value *}
max_value : real; {* Maximum Value *}
x : byte; {* Column *}
y : byte {* Row *}
) : char; {* Terminator *}
{* *}
{* This routine does basically the *}
{* thing as Get_Str only for numbers *}
{* There are more options however. *}
{* Basically Min and Max Value allow *}
{* to specify the range of acceptable *}
{* values and DECIMALS allows you to *}
{* specify the number of decimal *}
{* places desired *}
{**************************************}
var
i1,i2 : integer;
s1 : long_string;
s2 : long_string;
s3 : long_string;
inchar : char;
begin
str(value:1:decimals,s1); {Convert to a string}
str(max_value:1:decimals,s3); {find out how long a string max val is}
repeat {Main Loop}
s2 := '';
valid_set := numbers;
inchar := get_str(s1,length(s3),x,y,false); {Get_Str does the }
{work}
for i2 := 1 to length(s1) do {Strip out non digits}
if s1[i2] in (numbers - [','])
then
s2 := s2 + s1[i2];
val(s2,value,i1); {Find out its value}
until (value >= min_value) and (value <= max_value) and (i1 = 0); {do it }
{until its right}
gotoxy(x,y);
write_neatly(output,value,length(s3),decimals); {print the result}
valid_set := allchars;
get_num := inchar; {Assign the terminator}
end;
{18**************************************************************************}
procedure frame( {* Frame the section of screen within *}
upperleftx, {* these bounds *}
upperlefty, {**************************************}
lowerrightx,
lowerrighty: integer);
var
i: integer;
begin
gotoxy(upperleftx,upperlefty);
write(chr(218));
gotoxy(upperleftx,lowerrighty);
write(chr(192));
gotoxy(lowerrightx,upperlefty);
write(chr(191));
gotoxy(lowerrightx,lowerrighty);
write(chr(217));
for i := upperleftx + 1 to lowerrightx - 1 do
begin
gotoxy(i,upperlefty);
write(chr(196));
gotoxy(i,lowerrighty);
write(chr(196));
end;
for i := upperlefty + 1 to lowerrighty - 1 do
begin
gotoxy(upperleftx,i);
write(chr(179));
gotoxy(lowerrightx,i);
write(chr(179));
end;
end; { Frame }
{19***************************************************************************}
procedure unframe( {* This routine does the opposite of *}
upperleftx, {* frame *}
upperlefty, {*************************************}
lowerrightx,
lowerrighty: integer);
var
i: integer;
begin
gotoxy(upperleftx, upperlefty);
write(' ');
for i:=upperleftx+1 to lowerrightx-1 do
write(' ');
write(' ');
for i:=upperlefty+1 to lowerrighty-1 do
begin
gotoxy(upperleftx , i);
write(' ');
gotoxy(lowerrightx, i);
write(' ');
end;
gotoxy(upperleftx, lowerrighty);
write(' ');
for i:=upperleftx+1 to lowerrightx-1 do
write(' ');
write(' ');
end; {UnFrame }
{20**************************************************************************}
function menu ( {* Display a Menu *}
item_list : menu_selections; {* List of Options on Menu *}
{* Last Item must be Null *}
{* String for proper operation*}
{* No more than 30 items per *}
menu_x : integer; {* X Location of Menu *}
menu_y : integer; {* Y Location of Menu *}
menu_title : menu_item; {* Title of Menu *}
title_x : integer; {* X Location of Title *}
title_y : integer; {* Y Location of Title *}
default : integer {* Default Selection *}
) : integer; {* Return the index of the *}
{* item selected by the user *}
{* *}
{*********************************************** *
* This Routine Displays a Menu on the screen at the location specified by *
* Menu_X and Menu_Y. The Menu Title is displayed in Reverse Video at the *
* Location specified by Title_X and Title_Y. The User selects an item from *
* the menu by using <CTRL>-E to move a reverse video cursor bar up and *
* <CTRL>-X to move it down. After the cursor is on the item desired by the *
* user, he must press return. At this point the routine returns the item *
* number of the selection. *
*****************************************************************************}
const
cr = #13;
up = #5;
dn = #24;
var
first_shown : integer;
last_shown : integer;
inchar : char;
menu_pointer : 1..15;
menu_length : 1..15;
last : integer;
last_y : integer;
width : integer;
len : integer;
maxlen : integer;
x1,x2,y1,y2 : integer;
i,j,k : integer;
instr : long_string;
ls : integer;
begin {Menu}
instr := '';
width := lower_right_x - upper_left_x + 1; {Calculate Window Size}
len := lower_right_y - upper_left_y + 1;
maxlen := len + 2;
if width > 70
then begin
gotoxy(1,1);
color(12,back_ground_color);
writeln('IMEX - (800) 222 - 9188');
color(15,back_ground_color2);
write(center(width,menu_title));
end
else begin
gotoxy(title_x,title_y);
color(15,back_ground_color2);
write(menu_title);
end;
color(15,back_ground_color);
if width > 38
then {If there is enough room, write out instructions}
begin {otherwise, they is out a luck}
maxlen := maxlen - 3;
frame(1,len-3,width-1,len);
gotoxy((width div 2) - 6,len-3);
write(#17);
rvson;
write('Instructions');
rvsoff;
write(#16);
textcolor(15);
gotoxy(2,len-2);
write(center(width-3,'Use '+#24+' and '+#25+' to Highlight a Selection'));
gotoxy(2,len-1);
write(center(width-3,' And '+#17+'─┘ to make the Selection'));
end;
inchar := ' '; {Initialize variables}
menu_pointer := 1;
{Display the actual menu selections and determine how many selections
are available}
maxlen := maxlen - menu_y;
menu_length := 1;
while (item_list[menu_length + 1] <> '*') and
(item_list[menu_length + 1] <> '' ) do
menu_length := menu_length + 1;
for i := 1 to menu_length do
if length(item_list[i]) > 40
then
item_list[i] := copy(item_list[i],1,40);
if maxlen > ((menu_length) * 2)
then
ls := 2
else
ls := 1;
first_shown := 1;
last_shown := menu_length;
while (last_shown * ls + menu_y) > maxlen do
last_shown := last_shown - 1;
menu_pointer := default;
if menu_pointer > menu_length
then
menu_pointer := last_shown;
i := 0;
for j := first_shown to last_shown do
begin
gotoxy(menu_x, menu_y + (i * ls));
write(item_list[j]:length(item_list[j]));
i := i + 1;
clreol;
end;
last_y := wherey;
last := first_shown;
if last = default
then
last := last_shown;
while inchar <> cr do {Main loop}
begin
if (menu_pointer < first_shown) or (menu_pointer > last_shown)
then
begin
while menu_pointer < first_shown do
begin
first_shown := first_shown - 1;
if first_shown < 1
then
first_shown := 1;
last_shown := last_shown - 1;
if last_shown < 1
then
last_shown := 1;
end;
while menu_pointer > last_shown do
begin
first_shown := first_shown + 1;
last_shown := last_shown + 1;
end;
if last_shown > menu_length
then
last_shown := menu_length;
i := 0;
for j := first_shown to last_shown do
begin
if j = menu_pointer
then
rvson;
gotoxy(menu_x, menu_y + (i * ls));
write(item_list[j]:length(item_list[j]));
if (item_list[j][length(item_list[j])] = ']') and (menu_pointer = j)
then
begin
write(^h,^h,'X]');
last_y := wherey;
end;
i := i + 1;
if j = menu_pointer
then
rvsoff;
clreol;
end;
end
else
begin
rvsoff;
if last = (menu_length)
then
last_y := (last_shown - first_shown) * ls + menu_y;
if last = 1
then
last_y := menu_y;
gotoxy(menu_x,last_y);
write(item_list[last]);
gotoxy(menu_x,menu_y + (menu_pointer - first_shown) * ls);
rvson;
last_y := wherey;
write(item_list[menu_pointer]:length(item_list[menu_pointer]));
if item_list[menu_pointer][length(item_list[menu_pointer])] = ']'
then
write(^h,^h,'X]');
rvsoff;
clreol;
end;
read(kbd,inchar); {get a character from the user}
click;
if (inchar = ^[) and not keypressed
then
begin
menu := default;
exit;
end;
last := menu_pointer;
if not (inchar in [^[,up,dn,cr])
then
begin
if inchar = #127
then
instr := ''
else
if inchar = ^h
then
delete(instr,length(instr),1)
else
instr := instr + inchar;
j := 0;
k := 0;
for i := 1 to menu_length do
if lower(instr) = lower(copy(item_list[i],1,length(instr)))
then
begin
inc(j);
if k = 0
then
k := i;
end;
if k <> 0
then
menu_pointer := k;
if (j = 1) or (j = 0)
then
instr := '';
end;
if (inchar = ^[) and keypressed
then {get the escape code}
read(kbd, inchar);
if inchar = ';'
then
begin
x1 := upper_left_x;
y1 := upper_left_y;
x2 := lower_right_x;
y2 := lower_right_y;
help;
window(x1,y1,x2,y2);
end;
if (inchar = up) or (inchar = 'H')
then
begin {They hit up arrow}
menu_pointer := menu_pointer - 1;
if menu_pointer < 1
then
menu_pointer := (menu_length);
instr := '';
end; {If}
if (inchar = dn) or (inchar = 'P')
then
begin {They hit down arrow}
menu_pointer := menu_pointer + 1;
if menu_pointer > menu_length
then
menu_pointer := 1;
instr := '';
end; {If}
end; {While}
beep(440); {They made a selection, beep once}
menu := menu_pointer; {to confirm}
end; {Menu}
{22**************************************************************************}
procedure window_frame(x1,y1, {* Create, frame and title a *}
x2,y2 : integer; {* window *}
title : menu_item);{**********************************}
var
center : integer;
begin
window(1,1,80,25);
frame(x1 - 1, y1 - 1,
x2 + 1, y2 + 1);
center := ((x2 - x1) div 2) + x1;
gotoxy(center - (length(title) div 2)-1,y1-1);
write(#17);
rvson;
write(title);
rvsoff;
write(#16);
window(x1,y1,x2,y2);
clear_window;
end;
{48**************************************************************************}
type
typelist = (ustr,lstr,ulstr,rnum,inum,yn,dte,phne,tme);
{ustr upper case string
lstr lower case string
ulstr upper lower case string
rnum real number
inum integer
yn yes/no reply
dte date
phne phone number
tme time}
function getform( var value;
vtype : typelist;
x,y,
dp,len : integer;
lstrg : long_string;
lx,ly : integer
) : char;
var
realval : real absolute value;
intval : integer absolute value;
strval : long_string absolute value;
boolval : boolean absolute value;
mval : real;
tint : integer;
tstr1,
tstr : long_string;
valid : boolean;
tchar : char;
begin
gotoxy(lx,ly);
highvideo;
write(lstrg);
case vtype of
ustr : begin
getform := get_str(strval,len,x,y,true);
valid_set := allchars;
end;
lstr : begin
valid_set := lowercase;
getform := get_str(strval,len,x,y,false);
strval := lower(strval);
valid_set := allchars;
end;
ulstr : getform := get_str(strval,len,x,y,false);
rnum : begin
valid_set := numbers;
val(replicate(len - dp - 1,'9'),mval,tint);
getform := get_num(realval,dp,0,mval,x,y);
valid_set := allchars;
end;
inum : begin
valid_set := numbers;
getform := get_num(mval,0,-32767,maxint,x,y);
intval := trunc(mval);
valid_set := allchars;
end;
yn : begin
valid_set := ['Y','N','y','n'];
gotoxy(x,y);
if boolval
then
tstr := 'Y'
else
tstr := 'N';
repeat
tchar := get_str(tstr,1,x,y,true);
until tstr[1] in ['Y','N'];
boolval := tstr = 'Y';
getform := tchar;
valid_set := allchars;
end;
dte : begin
valid := false;
valid_set := digits;
tstr := copy(strval,1,2);
repeat
getform := get_str(tstr,2,x,y,false);
valid := ((tstr[1] = '1') and (tstr[2] in ['0'..'2'])) or
((tstr[1] in [' ','0']) and (tstr[2] in ['0'..'9']));
until valid;
tstr1 := tstr + '/';
gotoxy(x+2,y);
write('/');
valid := false;
tstr := copy(strval,4,2);
repeat
getform := get_str(tstr,2,x+3,y,false);
valid := ((tstr[1] = '3') and (tstr[2] in ['0'..'1'])) or
((tstr[1] in [' ','0'..'2']) and (tstr[2] in ['0'..'9']));
until valid;
tstr1 := tstr1 + tstr + '/';
gotoxy(x+5,y);
write('/');
valid := false;
tstr := copy(strval,7,2);
repeat
getform := get_str(tstr,2,x+6,y,false);
valid := (tstr[1] in ['8','9']) and (tstr[2] in ['0'..'9']);
until valid;
strval := tstr1 + tstr;
valid_set := allchars;
end;
tme : begin
valid_set := digits;
valid := false;
tstr := copy(strval,1,2);
repeat
getform := get_str(tstr,2,x,y,false);
valid := ((tstr[1] = '1') and (tstr[2] in ['0'..'2'])) or
((tstr[1] in [' ','0']) and (tstr[2] in ['0'..'9']));
until valid;
tstr1 := tstr + ':';
gotoxy(x+2,y);
write('/');
valid := false;
tstr := copy(strval,4,2);
repeat
getform := get_str(tstr,2,x+3,y,false);
valid := (tstr[1] in [' ','0'..'5']) and (tstr[2] in ['0'..'9']);
until valid;
tstr1 := tstr1 + tstr + ':';
gotoxy(x+5,y);
write('/');
valid := false;
tstr := copy(strval,7,2);
repeat
getform := get_str(tstr,2,x+6,y,false);
valid := (tstr[1] in ['0'..'5']) and (tstr[2] in ['0'..'9']);
until valid;
strval := tstr1 + tstr;
valid_set := allchars;
end;
phne : begin
valid_set := digits;
valid := false;
gotoxy(x,y);
write('(');
tstr := copy(strval,2,3);
repeat
getform := get_str(tstr,3,x+1,y,false);
valid := tstr[2] in ['0','1'];
until valid;
tstr1 := '(' + tstr + ') ';
gotoxy(x+4,y);
write(') ');
tstr := copy(strval,7,3);
getform := get_str(tstr,3,x+6,y,false);
tstr1 := tstr1 + tstr + '-';
gotoxy(x+10,y);
write('-');
tstr := copy(strval,11,4);
getform := get_str(tstr,4,x+10,y,false);
tstr1 := tstr1 + tstr;
strval := tstr1;
valid_set := allchars;
end;
end;
gotoxy(lx,ly);
lowvideo;
write(lstrg);
end;
{*********************************************************************}
const monthmask = $000f;
daymask = $001f;
minutemask = $003f;
secondmask = $001f;
type dtstr = string[8];
{49*******************************************************************}
function getdate : dtstr;
var
allregs : register;
month, day,
year : string[2];
i : integer;
tstr : dtstr;
begin
allregs.ax := $2a * 256;
msdos(allregs);
str((allregs.dx div 256): 2,month);
str((allregs.dx mod 256): 2,day);
str((allregs.cx - 1900): 2,year);
tstr := month + '/' + day + '/' + year;
for i := 1 to 8 do
if tstr[i] = ' '
then
tstr[i] := '0';
getdate := tstr;
end; {getdate}
{50*******************************************************************}
function gettime : dtstr;
var
allregs : register;
hour, minute,
second : string[2];
i : integer;
tstr : dtstr;
begin
allregs.ax := $2c * 256;
msdos(allregs);
str((allregs.cx div 256): 2,hour);
str((allregs.cx mod 256): 2,minute);
str((allregs.dx div 256): 2,second);
tstr := hour + ':' + minute + ':' + second;
for i := 1 to 8 do
if tstr[i] = ' '
then
tstr[i] := '0';
gettime := tstr;
end; {gettime}
{51*******************************************************************}
procedure push_window(x1,y1,x2,y2 : integer);
var
temp : video_ptr;
i,j,k : integer;
begin
if screen = nil
then
screen := ptr($b000,0);
new(temp);
temp^.x1 := x1;
temp^.y1 := y1;
temp^.x2 := x2;
temp^.y2 := y2;
getmem(temp^.screen_store,((x2 - x1 + 1) * (y2 - y1 + 1)) * 2);
temp^.next_screen := screen_stack;
k := 1;
for i := y1 to y2 do
for j := x1 to x2 do
begin
temp^.screen_store^[k] := screen^[i][j];
inc(k);
end;
screen_stack := temp;
end;
{*************************}